/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __COMPATIBILITY_H
#define __COMPATIBILITY_H

//! Inclusion of conditional libraries
#ifdef HAVE_CONFIG_H
	#include <config.h>
#endif
#if (defined HAVE_CV_H || defined USE_OPENCV)
	#include <cv.h>
#endif
#if (defined HAVE_CXCORE_H || defined USE_OPENCV)
	#include <cxcore.h>
#endif
#if (defined HAVE_CVAUX_H || defined USE_OPENCV)
	#include <cvaux.h>
#endif
#if (defined HAVE_HIGHGUI_H || defined USE_OPENCV)
	#include <highgui.h>
#endif

#ifdef _WIN32
#include <windows.h>
	//! Windows definitions
	#ifdef EAPM_EXPORTS
		#define EVOLUTIVELIB_API __declspec(dllexport)
	#else
		#define EVOLUTIVELIB_API __declspec(dllimport)
	#endif
	
	#ifdef USE_OPENCV
		#include <cv.h>
		#include <cvaux.h>
		#include <cxcore.h>
		#include <highgui.h>
	#endif
	#define isinf(x) !_finite(x)
	#define isnan(x) _isnan(x)
	
	#include <math.h>
	#define RAND_VALUE() (static_cast<double>(rand())/static_cast<double>(RAND_MAX))
	//#define LoadDynamicLibrary(X) LoadLibrary(X)
#else
	//! Linux definitions
	#include <stdlib.h>
	#define EVOLUTIVELIB_API 
	#define RAND_VALUE() ((double)random()/(double)RAND_MAX)
	//#define LoadDynamicLibrary(X) dlopen(X)

	//! If all the OpenCV headers are available, define the constant to use them into the library
	#if (defined HAVE_CONFIG_H && defined HAVE_CXCORE_H && defined HAVE_CVAUX_H && defined HAVE_HIGHGUI_H)
		#define USE_OPENCV
	#endif
#endif

//! Additional definitions
#ifndef PI
	#define PI 3.14159265358979323846
#endif
#ifndef EPS
	#define EPS 0.000001
#endif
#ifndef IO_CLASSNAME_LEN
	#define IO_CLASSNAME_LEN 50
#endif

//! If the OpenCV are not available, define some simple types.
#ifndef USE_OPENCV
	typedef struct CvRect
	{
		int x;
		int y;
		int width;
		int height;
	}
	CvRect;
	typedef struct
	{
		int width;
		int height;
	}
	CvSize;
	typedef struct CvPoint
	{
		int x;
		int y;
	}
	CvPoint;
	#if defined _MSC_VER || defined __BORLANDC__
		typedef __int64 int64;
		typedef unsigned __int64 uint64;
	#else
		typedef long long int64;
		typedef unsigned long long uint64;
	#endif
	typedef union Cv64suf
	{
		int64 i;
		uint64 u;
		double f;
	}
	Cv64suf;
	
	//! Function to round a double value
	#if defined __cplusplus	
		inline int cvRound( double value )
	#elif (defined WIN32 || defined WIN64) && !defined __GNUC__
		__inline int cvRound( double value )
	#else
		static int cvRound( double value )
	#endif
		{
		#if CV_SSE2
			__m128d t = _mm_load_sd( &value );
			return _mm_cvtsd_si32(t);
		#elif defined WIN32 && !defined WIN64 && defined _MSC_VER
			int t;
			__asm
			{
				fld value;
				fistp t;
			}
			return t;
		#elif (defined HAVE_LRINT) || (defined WIN64 && !defined EM64T && defined CV_ICC)
			return (int)lrint(value);
		#else
			/*
			 the algorithm was taken from Agner Fog's optimization guide
			 at http://www.agner.org/assem
			 */
			Cv64suf temp;
			temp.f = value + 6755399441055744.0;
			return (int)temp.u;
		#endif
		}

	//! Functions to throw exteptions in case of dependant functions and classes
	#define OPENCV_ERROR_FNC(FUNC_NAME) throw CEvolutiveLibException("This function can only be used with OpenCV support.",__FILE__,__LINE__,FUNC_NAME);
	#define OPENCV_ERROR_CLASS(FUNC_NAME) throw CEvolutiveLibException("This class can only be used with OpenCV support.",__FILE__,__LINE__,FUNC_NAME);
#endif

#endif //__COMPATIBILITY_H
